package org.smoozik.app.mode.generator;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;

import org.smoozik.app.common.partition.PartitionClient;
import org.smoozik.app.common.partition.PartitionPanel;
import org.smoozik.app.common.partition.component.UIPartition;
import org.smoozik.app.common.piano.PianoPanel;
import org.smoozik.app.ihm.AbstractFigure;
import org.smoozik.app.ihm.Constants;
import org.smoozik.app.ihm.Smoozik;
import org.smoozik.app.mode.FigureManager;
import org.smoozik.app.mode.GameManager;
import org.smoozik.app.mode.Mode;
import org.smoozik.app.mode.ModeSettings;
import org.smoozik.services.musictheory.Figure;

public class GeneratorMode implements ActionListener, Mode, PartitionClient {

	private JPanel mainPanel;
	Smoozik frame;

	private PartitionPanel partitionPanel;
	private PianoPanel pianoPanel;
	private FigureManager figureManager;
	private GameManager gameManager;
	private GeneratorListener generatorListener;
	private GeneratorSettings settings;

	// Settings attributes
	private int key;
	private int nbNotes;
	private String paramFigure;
	private int paramSharpBemol;
	private int paramRenversement;
	int timerSpeed;
	int paramMidPart;
	int paramSense;

	private JLabel generatedLabel;

	// Timer used to make the notes move in line
	private Timer timer;

	public GeneratorMode(Smoozik frame) {
		super();
		this.frame = frame;

		// default application parameters
		key = Constants.F_KEY;
		nbNotes = 7;
		paramFigure = Constants.FIGURE_CHORD;
		timerSpeed = 2;
		paramMidPart = -7;
		paramSharpBemol = 1;
		paramRenversement = Constants.DEFAULT_RENVERSEMENT;
		paramSense = Constants.LEFT_TO_RIGHT;

		// Creation of the managers
		gameManager = new GameManager();

		generatorListener = new GeneratorListener(this);

		UIPartition partition = new UIPartition(key);

		figureManager = new FigureManager(partition);

		// TODO FIXME
		updateNbNotes(this.nbNotes);

		// creation of the frame components
		initPanel();

		// TODO FIXME
		updateMidPart("" + this.paramMidPart);

		updateParamFigure(this.paramFigure);

		// start mode
		startTimer();
		resteNotes();
//		this.partitionPanel.resetFigureMargin();
		updateSense(this.paramSense);

		settings = new GeneratorSettings(this);

	}

	public GameManager getGameManager() {
		return gameManager;
	}

	public void setGameManager(GameManager gameManager) {
		this.gameManager = gameManager;
	}

	public int getParamSense() {
		return paramSense;
	}

	public void setParamSense(int paramSense) {
		this.paramSense = paramSense;
	}

	public int getKey() {
		return key;
	}

	public void setKey(int key) {
		this.key = key;
	}

	public int getNbNotes() {
		return nbNotes;
	}

	public void setNbNotes(int nbNotes) {
		this.nbNotes = nbNotes;
	}

	public int getParamMidPart() {
		return paramMidPart;
	}

	public void setParamMidPart(int paramMidPart) {
		this.paramMidPart = paramMidPart;
	}

	public String getParamFigure() {
		return paramFigure;
	}

	public void setParamFigure(String paramFigure) {
		this.paramFigure = paramFigure;
	}

	public int getParamSharpBemol() {
		return paramSharpBemol;
	}

	public void setParamSharpBemol(int paramSharpBemol) {
		this.paramSharpBemol = paramSharpBemol;
	}

	public int getParamRenversement() {
		return paramRenversement;
	}

	public void setParamRenversement(int paramRenversement) {
		this.paramRenversement = paramRenversement;
	}

	public FigureManager getFigureManager() {
		return figureManager;
	}

	public void setFigureManager(FigureManager figureManager) {
		this.figureManager = figureManager;
	}

	public int getTimerSpeed() {
		return timerSpeed;
	}

	public void setTimerSpeed(int speed) {
		this.timerSpeed = speed;
	}

	public PartitionPanel getPanel() {
		return partitionPanel;
	}

	public void setPanel(PartitionPanel panel) {
		this.partitionPanel = panel;
	}

	public void initPanel() {
		JPanel south = new JPanel();
		JPanel east = new JPanel();
		JPanel west = new JPanel(new BorderLayout());
		JPanel top = new JPanel();
		mainPanel = new JPanel(new BorderLayout());

		partitionPanel = new PartitionPanel(figureManager);
		partitionPanel.setPartitionClient(this);
		pianoPanel = new PianoPanel();
		JPanel center = new JPanel(new BorderLayout());

		JScrollPane jsp = new JScrollPane(partitionPanel);
		
		center.add(jsp, BorderLayout.CENTER);
		center.add(pianoPanel, BorderLayout.SOUTH);

		mainPanel.add(center, BorderLayout.CENTER);
		mainPanel.add(top, BorderLayout.NORTH);
		mainPanel.add(east, BorderLayout.EAST);
		mainPanel.add(west, BorderLayout.WEST);
		mainPanel.add(south, BorderLayout.SOUTH);

		// center.setBackground(Color.ORANGE);
//		partitionPanel.setBackground(Color.BLUE);
		partitionPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		this.partitionPanel.setPreferredSize(new Dimension(
				Constants.DEFAULT_LENGTH, 500));

//		pianoPanel.setBackground(Color.RED);
		pianoPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
		this.pianoPanel.setSize(new Dimension(Constants.DEFAULT_LENGTH, 90));
		this.pianoPanel.setPreferredSize(new Dimension(
				Constants.DEFAULT_LENGTH, 90));

		top.setBackground(Color.DARK_GRAY);
		east.setBackground(Color.WHITE);
		west.setBackground(Color.WHITE);
		south.setBackground(Color.DARK_GRAY);

		mainPanel.setBackground(Color.WHITE);

		// South buttons
		JButton playButton = new JButton(Constants.PLAY_LABEL);
		south.add(playButton);
		playButton.addActionListener(generatorListener);
		JButton stopButton = new JButton(Constants.STOP_LABEL);
		south.add(stopButton);
		stopButton.addActionListener(generatorListener);
		JButton replayButton = new JButton(Constants.REPLAY_LABEL);
		south.add(replayButton);
		replayButton.addActionListener(generatorListener);
		JButton resetButton = new JButton(Constants.RESET_LABEL);
		south.add(resetButton);
		resetButton.addActionListener(generatorListener);
		JButton plusButton = new JButton(Constants.PLUS_LABEL);
		south.add(plusButton);
		plusButton.addActionListener(generatorListener);
		JButton minusButton = new JButton(Constants.MINUS_LABEL);
		south.add(minusButton);
		minusButton.addActionListener(generatorListener);

		partitionPanel.setFocusable(true);
		partitionPanel.requestFocusInWindow();

		this.generatedLabel = new JLabel();
		east.add(generatedLabel);
		frame.pack();
	}

	public void buildButtonsFromList(String[] labelList, JPanel panel) {

		String labelButton = null;
		JButton noteButton = null;

		for (int i = 0; i < labelList.length; i++) {
			labelButton = labelList[i];
			noteButton = new JButton(labelButton);
			panel.add(noteButton);
			noteButton.addActionListener(generatorListener);
		}
	}

	public void initNote() {
		this.initLabels();
	}

	public void initLabels() {
		generatedLabel.setText("");
	}

	public void generateFigure() {
		initNote();

		Figure figure = partitionPanel.addNewFigure(paramFigure,
				paramSharpBemol, paramRenversement, Constants.LINE_TRAINER_ID);

		pianoPanel.setCurrentFigure(figure);

		if (figure != null) {
			this.generatedLabel.setText(figure.toString());
		}

		playFigure();
	}

	public void updateFigure(AbstractFigure figure) {
		this.figureManager.setCurrentFigure(figure);
		this.partitionPanel.addFigure(figure);
	}

	public void resteNotes() {
		this.partitionPanel.resetLists();
		initNote();
	}

	/**
	 * Plays a sound according to the currentFigure, the last generated figure
	 */
	public void playFigure() {
		Figure f = this.figureManager.getCurrentFigure();
		frame.getSoundPlayer().playFigure(f);
	}

	public void stopSounds() {
		frame.getSoundPlayer().stopNotes();
	}

	// Settings frame

	public void start() {
		this.gameManager.initGame();
		generateFigure();
		startTimer();
	}

	// Timer methods

	public void startTimer() {
		if (timer == null) {
			timer = new Timer(10, this);
			timer.setInitialDelay(0);
			timer.start();
		}
	}

	public void stopTimer() {
		if (this.timer != null) {
			this.timer.stop();
		}
		this.timer = null;
	}

	public void increaseSpeed() {
		this.timerSpeed++;
	}

	public void decreaseSpeed() {
		if (this.timerSpeed > 1) {
			this.timerSpeed--;
		}
	}

	public void actionPerformed(ActionEvent e) {
//		this.figureManager.moveAllPointBy(timerSpeed
//				* Constants.TIMER_SENSE[this.paramSense]);
		frame.repaint();
		frame.validate();
	}

	public void updateParamFigure(String figure) {
		// this.noteButtonsPanel.setVisible(figure.equals(Constants.NOTE_LABEL));
		// this.chordButtonsPanel.setVisible(figure.equals(Constants.CHORD_LABEL));
		// this.intervalButtonsPanel.setVisible(figure
		// .equals(Constants.INTERVAL_LABEL));

		setParamFigure(figure);
	}

	public int getPartitionMidLevel() {
		return this.figureManager.getPartition().getMiddleIndex();
	}

	public void updateKey(int key) {
		this.figureManager.setKey(key);
//		this.figureManager.refreshNotes();
		setKey(key);
	}

	public void updateNbNotes(int nb) {
		this.figureManager.setNbNotes(nb);
		setNbNotes(nb);
	}

	public void updateMidPart(String text) {
		if (text != null && text.trim().length() != 0) {
			this.figureManager.getPartition().setMiddleIndex(
					Integer.parseInt(text));
		}
	}

	public void updateSenseParam(int sense) {
		if (sense != paramSense) {
			resteNotes();
		}
		updateSense(sense);
	}

	public void updateSense(int sense) {
		this.figureManager.getPartition().setMargin(Constants.MARGIN[sense]);
//		this.figureManager.refreshNotes();
		setParamSense(sense);
	}

	@Override
	public void keyPressed(Figure figure) {
		if(figure != null) {
			frame.getSoundPlayer().playFigure(figure);
			this.generatedLabel.setText(figure.toString());
		}
	}

	@Override
	public void keyReleased() {
		// this.stopSounds();
		// if (this.getGameManager().isGameStarted()) {
		// this.validateAnswer();
		// }
	}

	@Override
	public JPanel getMainPanel() {
		return this.mainPanel;
	}

	@Override
	public ModeSettings getModeSettings() {
		// TODO Auto-generated method stub
		return this.settings;
	}

	@Override
	public String toString() {

		return Constants.GENERATOR_LABEL;
	}

	@Override
	public String getId() {
		return Constants.GENERATOR_ID;
	}

	@Override
	public void resize(Dimension d) {
		mainPanel.setPreferredSize(d);
	}

}
